﻿using Authentication.Core.Configuration;
using Authentication.Core.Data;
using Authentication.Model.Interface;
using Authentication.Model.Model;
using Common.Contract.Authentication.Record;
using Common.Contract.Paging;
using Common.Contract.SystemConfig.Record;
using Common.Data.Repository.Enum;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Globalization;
using System.Linq;

namespace Authentication.Provider
{
    public class ChangeDaoProvider : GenericProvider, IChangeDaoProvider
    {
        public List<ChangeDaoRequest> RetrieveListChangeDaoRequest(out int totalRecord, UserRecord currentUser, FilterRecord textSearch = null, int pagesize = 0, int pageindex = 0, SortRecord sortRecord = null)
        {
            int curIdGroup = int.Parse(currentUser.GroupIdentifier);
            var data = repository.DbContext as AuthenticationEntities;
            var query = from x in data.ChangeDaoRequests.Include(x => x.Branch)
                        select x;
            if (currentUser.GroupIdentifier.Equals("3"))
            {
                query = query.Where(x => x.BranchCodeSme.Equals(currentUser.BranchCode));
                query = query.Where(x => x.Status == (int)StatusChangeDaoEnum.Create && x.Pic.Equals(currentUser.UserName) || x.Status != (int)StatusChangeDaoEnum.Create);
            }
            if (currentUser.GroupIdentifier.Equals("2"))
            {
                //query = query.Where(x => x.BranchCodeSme.Equals(currentUser.BranchCode));
                query = query.Where(x => x.Status == (int)StatusChangeDaoEnum.Create && x.Pic.Equals(currentUser.UserName) || x.Status != (int)StatusChangeDaoEnum.Create);
            }
            if (currentUser.GroupIdentifier.Equals("6") || currentUser.GroupIdentifier.Equals("4"))
            {
                query = query.Where(x => x.Pic.Equals(currentUser.UserName));
            }
            if (textSearch.CreateDaoRequestStatus.HasValue)
            {
                query = query.Where(x => x.Status == textSearch.CreateDaoRequestStatus);
            }
            else
            {
                query = query.Where(x => string.IsNullOrEmpty(x.RejectPerson) || x.GroupIdReject.Value <= curIdGroup);
            }
            if (SystemConfiguration.UserMBDApprovedDao.Contains(currentUser.UserName))
            {
                query = query.Where(x => x.Status != (int)StatusChangeDaoEnum.Request);
                query = query.Where(x => x.Branch.Region.Contains("MBD"));
            }
            if (SystemConfiguration.UserHOApprovedDao.Contains(currentUser.UserName) && !textSearch.IsExport)
            {
                query = query.Where(x => !x.Branch.Region.Contains("MBD"));
            }
            if (SystemConfiguration.UserBICApprovedDao.Contains(currentUser.UserName))
            {
                query = query.Where(x => x.Status != (int)StatusChangeDaoEnum.BranchApproved && x.Status != (int)StatusChangeDaoEnum.Request && x.Status != (int)StatusChangeDaoEnum.Create);
            }
            if ((SystemConfiguration.UserHOApprovedDao.Contains(currentUser.UserName) || SystemConfiguration.UserMBDApprovedDao.Contains(currentUser.UserName)) && !textSearch.IsExport)
            {
                query = query.Where(x => x.Status != (int)StatusChangeDaoEnum.Request && x.Status != (int)StatusChangeDaoEnum.Create);
            }
            if (textSearch.IsExportDeviation)
            {
                query = query.Where(x => x.Status == (int)StatusChangeDaoEnum.Done || x.Status == (int)StatusChangeDaoEnum.SendEmail);
            }
            if (!string.IsNullOrEmpty(textSearch.Region) && textSearch.Region.Trim() != "null")
            {
                query = query.Where(x => textSearch.Region.ToUpper().Contains(x.Branch.Region.ToUpper()));
            }
            if (!string.IsNullOrEmpty(textSearch.Branch) && textSearch.Branch.Trim() != "null")
            {
                query = query.Where(x => textSearch.Branch.ToUpper().Contains(x.Branch.BranchId.ToUpper()));
            }
            if (!string.IsNullOrEmpty(textSearch.RequestId))
            {
                query = query.Where(x => ("CHD" + x.Id.ToString()).Contains(textSearch.RequestId));
            }
            if (!string.IsNullOrEmpty(textSearch.DaoName))
            {
                query = query.Where(x => x.Pic.Contains(textSearch.DaoName));
            }
            if (!string.IsNullOrEmpty(textSearch.Description) && textSearch.Description != "-1")
            {
                int reason = int.Parse(textSearch.Description);
                query = query.Where(x => x.Reason == reason);
            }
            if (!string.IsNullOrEmpty(textSearch.RequestStatus) && textSearch.RequestStatus != "-1")
            {
                int requestStatus = int.Parse(textSearch.RequestStatus);
                switch (requestStatus)
                {
                    case 11:
                        query = query.Where(x => x.Status == (int)StatusChangeDaoEnum.Reject && x.GroupIdReject == 3);
                        break;
                    case 12:
                        query = query.Where(x => x.Status == (int)StatusChangeDaoEnum.Reject && x.GroupIdReject == 2);
                        break;
                    case 13:
                        query = query.Where(x => x.Status == (int)StatusChangeDaoEnum.Reject && SystemConfiguration.UserBICApprovedDao.Contains(x.RejectPerson));
                        break;
                    case 14:
                        query = query.Where(x => x.Status == (int)StatusChangeDaoEnum.Reject && x.Pic.Equals(x.RejectPerson));
                        break;
                    default:
                        query = query.Where(x => x.Status == requestStatus);
                        break;
                }
            }
            DateTime ToDateCompare = DateTime.Now.AddMonths(1);
            DateTime FromDateCompare = DateTime.Now;
            if (!string.IsNullOrEmpty(textSearch.CusOpenDate))
            {
                List<string> listFilter = textSearch.CusOpenDate.Split('-').ToList();
                FromDateCompare = DateTime.ParseExact(listFilter.FirstOrDefault().Trim(), "dd/MM/yyyy", CultureInfo.InvariantCulture);
                ToDateCompare = DateTime.ParseExact(listFilter.LastOrDefault().Trim(), "dd/MM/yyyy", CultureInfo.InvariantCulture);
                query = query.Where(x => x.CreatedDate >= FromDateCompare && x.CreatedDate <= ToDateCompare);
            }
            if (textSearch.IsExportDeviation)
            {
                query = query.Where(x => x.IsDeviation == 1);
            }
            totalRecord = query.Count();
            bool isAsc = true;
            if (sortRecord != null)
            {
                isAsc = sortRecord.SortDir.FirstOrDefault().Equals("asc");

            }
            if (isAsc)
            {
                query = query.OrderBy(x => x.Id);
            }
            else
            {
                query = query.OrderByDescending(x => x.Id);
            }
            if (pagesize > 0 && pageindex >= 0)
            {
                query = query.Skip(pageindex * pagesize).Take(pagesize);
            }

            return query.ToList();
        }
        public List<ChangeDaoRequest> RetrieveListChangeDaoRequestByDao(out int totalRecord, UserRecord currentUser, List<int> listChangeDaoId, FilterRecord textSearch = null, int pagesize = 0, int pageindex = 0, SortRecord sortRecord = null)
        {
            int curIdGroup = int.Parse(currentUser.GroupIdentifier);
            var data = repository.DbContext as AuthenticationEntities;
            var query = from x in data.ChangeDaoRequests.Include(x => x.Branch)
                        where listChangeDaoId.Contains(x.Id) || x.Pic.Equals(currentUser.UserName)
                        select x;
            //if (currentUser.GroupIdentifier.Equals("6") || currentUser.GroupIdentifier.Equals("4"))
            //{
            //    query = query.Where(x => x.Pic.Equals(currentUser.UserName));
            //}
            if (textSearch.CreateDaoRequestStatus.HasValue)
            {
                query = query.Where(x => x.Status == textSearch.CreateDaoRequestStatus);
            }
            else
            {
                query = query.Where(x => string.IsNullOrEmpty(x.RejectPerson) || x.GroupIdReject.Value <= curIdGroup);
            }
            if (!string.IsNullOrEmpty(textSearch.RequestId))
            {
                query = query.Where(x => ("CHD" + x.Id.ToString()).Contains(textSearch.RequestId));
            }
            if (!string.IsNullOrEmpty(textSearch.DaoName))
            {
                query = query.Where(x => x.Pic.Contains(textSearch.DaoName));
            }
            if (!string.IsNullOrEmpty(textSearch.Description) && textSearch.Description != "-1")
            {
                int reason = int.Parse(textSearch.Description);
                query = query.Where(x => x.Reason == reason);
            }
            if (!string.IsNullOrEmpty(textSearch.RequestStatus) && textSearch.RequestStatus != "-1")
            {
                int requestStatus = int.Parse(textSearch.RequestStatus);
                switch (requestStatus)
                {
                    case 11:
                        query = query.Where(x => x.Status == (int)StatusChangeDaoEnum.Reject && x.GroupIdReject == 3);
                        break;
                    case 12:
                        query = query.Where(x => x.Status == (int)StatusChangeDaoEnum.Reject && x.GroupIdReject == 2);
                        break;
                    case 13:
                        query = query.Where(x => x.Status == (int)StatusChangeDaoEnum.Reject && SystemConfiguration.UserBICApprovedDao.Contains(x.RejectPerson));
                        break;
                    case 14:
                        query = query.Where(x => x.Status == (int)StatusChangeDaoEnum.Reject && x.Pic.Equals(x.RejectPerson));
                        break;
                    default:
                        query = query.Where(x => x.Status == requestStatus);
                        break;
                }
            }
            DateTime ToDateCompare = DateTime.Now.AddMonths(1);
            DateTime FromDateCompare = DateTime.Now;
            if (!string.IsNullOrEmpty(textSearch.CusOpenDate))
            {
                List<string> listFilter = textSearch.CusOpenDate.Split('-').ToList();
                FromDateCompare = DateTime.ParseExact(listFilter.FirstOrDefault().Trim(), "dd/MM/yyyy", CultureInfo.InvariantCulture);
                ToDateCompare = DateTime.ParseExact(listFilter.LastOrDefault().Trim(), "dd/MM/yyyy", CultureInfo.InvariantCulture);
                query = query.Where(x => x.CreatedDate >= FromDateCompare && x.CreatedDate <= ToDateCompare);
            }
            totalRecord = query.Count();
            bool isAsc = true;
            if (sortRecord != null)
            {
                isAsc = sortRecord.SortDir.FirstOrDefault().Equals("asc");

            }
            if (isAsc)
            {
                query = query.OrderBy(x => x.Id);
            }
            else
            {
                query = query.OrderByDescending(x => x.Id);
            }
            if (pagesize > 0 && pageindex >= 0)
            {
                query = query.Skip(pageindex * pagesize).Take(pagesize);
            }

            return query.ToList();
        }

        public List<ChangeDaoCif> RetrieveChangeDaoCifByDao(UserRecord currentUser)
        {
            var data = repository.DbContext as AuthenticationEntities;
            var query = from x in data.ChangeDaoCifs
                        join y in data.Customers on x.Cif equals y.Cif
                        where x.NewDao == currentUser.Dao || y.Dao == currentUser.Dao
                        select x;
            return query.ToList();

        }
        public List<ChangeDaoProduct> RetrieveListChangeDaoProductByDao(List<string> listDao)
        {
            var data = repository.DbContext as AuthenticationEntities;
            var query = from x in data.ChangeDaoProducts
                        where listDao.Contains(x.Dao)
                        select x;
            return query.ToList();
        }
        public List<ChangeDaoProductChecked> RetrieveListChangeDaoProductByDao(UserRecord currentUser)
        {
            var data = repository.DbContext as AuthenticationEntities;
            var query = from x in data.ChangeDaoProductCheckeds
                        where x.Dao == currentUser.Dao
                        select x;
            return query.ToList();
        }
        public List<ChangeDaoCif> RetrieveChangeDaoCif(out int totalRecord, UserRecord currentUser, int changeRequestId, int pagesize = 0, int pageindex = 0)
        {
            var data = repository.DbContext as AuthenticationEntities;
            var query = from x in data.ChangeDaoCifs
                        where x.ChangeDaoId == changeRequestId
                        select x;

            totalRecord = query.Count();

            query = query.OrderBy(x => x.Id);
            if (pagesize > 0 && pageindex >= 0)
            {
                query = query.Skip(pageindex * pagesize).Take(pagesize);
            }

            return query.ToList();
        }
        public List<ChangeDaoCif> RetrieveChangeDaoCif(UserRecord currentUser, List<int> changeRequestId, bool isExport = false)
        {
            var data = repository.DbContext as AuthenticationEntities;
            var query = from x in data.ChangeDaoCifs
                        where changeRequestId.Contains(x.ChangeDaoId)
                        select x;
            if (isExport)
            {
                query = query.Where(x => x.Status == (int)StatusChangeDaoCifEnum.Aproved);
            }
            query = query.OrderBy(x => x.Id);

            List<ChangeDaoCif> result = query.Count() > 0 ? query.ToList() : new List<ChangeDaoCif>();
            return result;
        }
        public List<ChangeDaoProduct> RetrieveListChangeDaoProductByCif(List<ChangeDaoCifRecord> listCif, UserRecord currentUser)
        {
            var dicCif = listCif.Select(x => x.Cif).ToList();
            //var listDao = listRecord.Select(x => x.OldDao).ToList();

            var data = repository.DbContext as AuthenticationEntities;
            var query = from x in data.ChangeDaoProducts
                        where currentUser.BranchId == x.BranchId && dicCif.Contains(x.Cif)
                        select x;
            return query.ToList();
        }
        public List<ChangeDaoProductChecked> RetrieveListChangeDaoProductByCifChecked(List<string> listCif, List<int> changeRequestId, bool isExport = false)
        {
            var data = repository.DbContext as AuthenticationEntities;
            var query = from x in data.ChangeDaoProductCheckeds
                        where changeRequestId.Contains(x.ChangeDaoRequestId.Value)
                        select x;
            if (isExport)
            {
                query = query.Where(x => x.Status == (int)StatusChangeDaoCifEnum.Aproved);
            }
            return query.ToList();
        }
        public ChangeDaoRequest SaveChangeDaoRequest(ChangeDaoRequest record)
        {
            try
            {
                var data = repository.DbContext as AuthenticationEntities;
                repository.ChangeDaoRequests.Add(record);
                repository.UnitOfWork.SaveChanges();
            }
            catch
            {
                return null;
            }
            return record;
        }

        public bool SaveChangeDaoCif(List<ChangeDaoCif> changeDaoCif, List<ChangeDaoProductChecked> listChangeProduct)
        {
            try
            {
                var data = repository.DbContext as AuthenticationEntities;
                changeDaoCif.ForEach(x =>
                {
                    repository.Add<ChangeDaoCif>(x);
                });
                listChangeProduct.ForEach(x =>
                {
                    repository.Add<ChangeDaoProductChecked>(x);
                });
                repository.UnitOfWork.SaveChanges();
            }
            catch
            {
                return false;
            }
            return true;
        }
        public bool SaveChangeDaoCifMultiple(List<ChangeDaoCifRecord> listChangeDaoCif, List<ChangeDaoCif> changeDaoCif, List<ChangeDaoProduct> listProduct)
        {
            try
            {
                var data = repository.DbContext as AuthenticationEntities;
                int changeDaoCifId = (from y in data.ChangeDaoCifs
                                      select y.Id).Count() > 0 ? (from y in data.ChangeDaoRequests select y.Id).Max() : 0;
                int changeDaoProductId = (from y in data.ChangeDaoProductCheckeds
                                          select y.Id).Count() > 0 ? (from y in data.ChangeDaoRequests select y.Id).Max() : 0;
                changeDaoCif.ForEach(x =>
                {
                    changeDaoCifId = changeDaoCifId + 1;
                    x.Id = changeDaoCifId;
                    repository.Add<ChangeDaoCif>(x);
                });
                repository.UnitOfWork.SaveChanges();
                var dicProduct = listProduct.ToDictionary(x => x.NoProduct);
                changeDaoCif.ForEach(x =>
                {
                    var changeDaoCifHaveProductItem = listChangeDaoCif.Where(y => y.ListChangeDaoProduct != null && y.ListChangeDaoProduct.Count > 0);
                    if (changeDaoCifHaveProductItem != null && changeDaoCifHaveProductItem.Count() > 0)
                    {
                        changeDaoCifHaveProductItem.SingleOrDefault(y => y.Cif.Equals(x.Cif) && y.NewDao.Equals(x.NewDao)).ListChangeDaoProduct.Where(y => dicProduct.ContainsKey(y.NoProduct)).Select(z => new ChangeDaoProductChecked
                        {
                            Cif = x.Cif,
                            Dao = string.IsNullOrEmpty(dicProduct[z.NoProduct].Dao) ? string.Empty : dicProduct[z.NoProduct].Dao,
                            BusinessDate = dicProduct[z.NoProduct].BusinessDate,
                            CreatedDate = DateTime.Now,
                            NoProduct = z.NoProduct,
                            TypeProduct = dicProduct[z.NoProduct].TypeProduct,
                            ChangeDaoRequestId = x.ChangeDaoId,
                            BranchId = dicProduct[z.NoProduct].BranchId,
                            Status = z.IsApproved ? (int)StatusChangeDaoCifEnum.Request : (int)StatusChangeDaoCifEnum.Reject
                        }).ToList().ForEach(p =>
                        {
                            changeDaoProductId = changeDaoProductId + 1;
                            p.Id = changeDaoProductId;
                            repository.Add<ChangeDaoProductChecked>(p);
                        });
                    }
                });
                repository.UnitOfWork.SaveChanges();
            }
            catch
            {
                return false;
            }
            return true;
        }

        public bool UpdateStatusChangeDaoRequest(ChangeDaoRequest checkUser)
        {
            var checkRecord = repository.FindOne<ChangeDaoRequest>(x => x.Id == checkUser.Id);
            if (checkRecord == null)
            {
                return false;
            }
            else
            {
                checkRecord.Status = checkUser.Status;
                if (checkUser.Status == (int)StatusChangeDaoEnum.Reject)
                {
                    checkRecord.RejectPerson = checkUser.RejectPerson;
                    checkRecord.GroupIdReject = checkUser.GroupIdReject;
                    checkRecord.RejectReason = checkUser.RejectReason;
                }
                checkRecord.UpdatedDate = DateTime.Now;
                repository.UnitOfWork.SaveChanges();
                return true;
            }
        }
        public bool UpdateStatusListChangeDaoRequest(int[] listId, int status)
        {

            var listCheckRecord = repository.Find<ChangeDaoRequest>(x => listId.Contains(x.Id)).ToList();
            if (listCheckRecord != null && listCheckRecord.Count() > 0)
            {
                listCheckRecord.ForEach(x =>
                {
                    x.Status = status;
                    x.UpdatedDate = DateTime.Now;
                });
            }
            repository.UnitOfWork.SaveChanges();
            return true;
        }
        public bool UpdateChangeDaoCif(List<ChangeDaoCif> listChangeDaoCifUpdate)
        {
            var dicChangeDaoCif = listChangeDaoCifUpdate.ToDictionary(x => x.Id);
            var listChangeCifID = listChangeDaoCifUpdate.Select(x => x.Id).ToList();

            var listCheckRecord = repository.Find<ChangeDaoCif>(x => listChangeCifID.Contains(x.Id)).ToList();

            if (listCheckRecord != null && listCheckRecord.Count() > 0)
            {
                listCheckRecord.ForEach(x =>
                {
                    x.Status = dicChangeDaoCif[x.Id].Status;
                });
            }
            repository.UnitOfWork.SaveChanges();
            return true;
        }
        public bool UpdateChangeDaoProduct(List<ChangeDaoProductChecked> listChangeDaoProductUpdate)
        {
            var dicChangeProduct = listChangeDaoProductUpdate.ToDictionary(x => x.Id);
            var listChangeProductID = listChangeDaoProductUpdate.Select(x => x.Id).ToList();

            var listCheckProductRecord = repository.Find<ChangeDaoProductChecked>(x => listChangeProductID.Contains(x.Id)).ToList();

            if (listCheckProductRecord != null && listCheckProductRecord.Count() > 0)
            {
                listCheckProductRecord.ForEach(x =>
                {
                    x.Status = dicChangeProduct[x.Id].Status;
                });
            }
            repository.UnitOfWork.SaveChanges();
            return true;
        }
        public ChangeDaoRequest RetrieveRequestByRequestId(int id, UserRecord currentUser)
        {
            var data = repository.DbContext as AuthenticationEntities;
            var query = from x in data.ChangeDaoRequests.Include(x => x.Branch)
                        where x.Id == id
                        select x;
            if (currentUser.GroupIdentifier.Equals("3"))
            {
                query = query.Where(x => x.BranchCodeSme.Equals(currentUser.BranchCode));
            }
            if (currentUser.UserName.Equals(SystemConfiguration.UserBICApprovedDao))
            {
                query = query.Where(x => x.Status != (int)StatusChangeDaoEnum.BranchApproved && x.Status != (int)StatusChangeDaoEnum.Request);
            }
            return query.FirstOrDefault();
        }

        public ChangeDaoRequest RetrieveChangeDaoRequestByIdAndItem(int id, List<ChangeDaoCifRecord> listChangeDaoCif, List<ChangeDaoProductCheckedRecord> listProduct)
        {
            var data = repository.DbContext as AuthenticationEntities;
            var query = from x in data.ChangeDaoRequests
                        where x.Id == id
                        select x;
            return query.FirstOrDefault();
        }

    }
}
